package org.example.study7;

public class MyBlockingQueue {
    // 定义一个数组来存放数据，具体的容量由构造方法中的参数决定
    private Integer[] elementData;  // 存储元素的数组
    private volatile int head = 0;  // 队头指针（volatile 保证可见性）
    private volatile int tail = 0;  // 队尾指针（volatile 保证可见性）
    private volatile int size = 0;  // 队列中元素的数量（volatile 保证可见性）
    // 构造
    public MyBlockingQueue(int capacity) {
        if (capacity <= 0) {
            throw new RuntimeException("队列容量必须大于0.");
        }
        elementData = new Integer[capacity]; // 初始化数组
    }

    // 插入数据的方法
    public void put(Integer value) throws InterruptedException {
        synchronized (this) { // 获取对象锁
            while (size >= elementData.length) { // 循环检查队列是否已满
                this.wait(); // 队列满时，释放锁并阻塞等待
            }
            elementData[tail] = value; // 在队尾插入元素
            tail++; // 移动队尾指针
            if (tail >= elementData.length) { // 处理循环逻辑
                tail = 0; // 队尾指针回到数组头部
            }
            size++; // 元素数量增加
            this.notifyAll(); // 唤醒所有等待的消费者线程
        }
    }

    // 获取数据的方法
    public synchronized Integer take() throws InterruptedException {
        while (size == 0) { // 循环检查队列是否为空
            this.wait(); // 队列空时，释放锁并阻塞等待
        }
        Integer value = elementData[head]; // 获取队头元素
        head++; // 移动队头指针
        if (head >= elementData.length) { // 处理循环逻辑
            head = 0; // 队头指针回到数组头部
        }
        size--; // 元素数量减少
        this.notifyAll(); // 唤醒所有等待的生产者线程
        return value; // 返回元素
    }

}

/*
解决的问题
1. 线程安全：通过 synchronized 保证对共享资源（head, tail, size）的原子操作。
2. 生产者-消费者协调：
当队列满时，生产者线程自动阻塞，避免数据覆盖。
当队列空时，消费者线程自动阻塞，避免无效轮询。
3. 资源高效利用：通过 wait()/notifyAll() 避免忙等待（busy-waiting），减少 CPU 空转。



现象
1. 队列满时的阻塞：
生产者线程调用 put() 时，若队列已满，会进入 WAITING 状态。
直到消费者线程调用 take() 取出数据后唤醒生产者。
2. 队列空时的阻塞：
消费者线程调用 take() 时，若队列为空，会进入 WAITING 状态。
直到生产者线程调用 put() 插入数据后唤醒消费者。
3. 循环队列的高效性：通过 head 和 tail 的循环移动，避免频繁扩容或数据拷贝。



实现原理
1. 循环数组：通过 head 和 tail 指针的循环移动，将线性数组模拟为环形队列。
2. 条件变量：通过 wait() 和 notifyAll() 实现线程间的协作。
3. 双重检查：使用 while 而非 if 检查队列状态，防止虚假唤醒（spurious wakeup）。*/